﻿namespace JoinBox.WPF;

using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;


#if false
  [CallerMemberName]特性是4.5才有,低版本可以可以自己仿照一个,也可以更换到Fody方案.
  需要向 .csproj 增加
  <PackageReference Include="System.Runtime">
  	<Version>4.0.0</Version>
  </PackageReference>
  <Reference Include="mscorlib.dll" />
#endif


/*
<Window x:Class="JoinBox.WPF.Thesaurus.Thesaurus"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local1="clr-namespace:JoinBox.WPF.Thesaurus.View"
    xmlns:local2="clr-namespace:JoinBox.WPF.Thesaurus.ViewModel"
    mc:Ignorable="d"
    Title="Test_demo" Height="350" Width="525">
<Grid Name="mygrid">
    <Grid.RowDefinitions>
        <RowDefinition Height="91*"/>
        <RowDefinition Height="93*"/>
        <RowDefinition Height="136*"/>
    </Grid.RowDefinitions>
    <TextBox x:Name="tbx_name" Text="{Binding Txt_Name, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Width="100" Margin="111,6,314,6" RenderTransformOrigin="0.388,1.631" Grid.Row="1" />
    <TextBox x:Name="tbx_age" Text="{Binding Txt_Age, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Width="100" Margin="304,2,121,10" RenderTransformOrigin="0.388,1.631" Grid.Row="1" />
    <Button Click="Btn_Click" Margin="0,24,0,24" Grid.Row="2">按钮+1</Button>
</Grid>
</Window>
 */

/// <summary>
/// 通知属性更改基类
/// </summary>
/// ViewModel需要通知界面时,需要继承<seealso cref="INotifyPropertyChanged"/>
public class ViewModelBase : INotifyPropertyChanged
{
    /// <summary>
    /// 属性值更改事件,初始化事件
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged = (send, e) => { };

    /// <summary>
    /// 通知属性更改
    /// </summary>
    /// <param name="propertyName">属性名</param>
#if NET35 || NET40
    public void OnPropertyChanged(string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
#else
    public void OnPropertyChanged([CallerMemberName] string? propertyName = "")
    {
        if (propertyName == null)
            return;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
#endif

    /// <summary>
    /// 设置属性函数,自动通知属性改变事件
    /// </summary>
    /// <typeparam name="T">属性类型</typeparam>
    /// <param name="storage">属性</param>
    /// <param name="value">属性值</param>
    /// <param name="propertyName">属性名</param>
    /// <returns>成功返回 <see langword="true"/>,反之 <see langword="false"/></returns>
#if NET35 || NET40
    protected virtual bool SetProperty<T>(ref T storage, T value, string? propertyName = null)
    {
        if (propertyName is null)
            return false;

        if (Equals(storage, value))
            return false;

        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }
#else
    protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string? propertyName = null)
    {
        if (object.Equals(storage, value))
            return false;

        storage = value;
        this.OnPropertyChanged(propertyName);

        return true;
    }
#endif

    /// <summary>
    /// 创建命令
    /// </summary>
    /// <param name="executeMethod">要调用的命令函数委托</param>
    /// <returns>WPF命令</returns>
    static protected RelayCommand CreateCommand(Action<object> executeMethod)
    {
        return CreateCommand(executeMethod, (o) => true);
    }

    /// <summary>
    /// 创建命令
    /// </summary>
    /// <param name="executeMethod">要调用的命令函数委托</param>
    /// <param name="canExecuteMethod">命令是否可以执行的委托</param>
    /// <returns>WPF命令</returns>
    static protected RelayCommand CreateCommand(Action<object> executeMethod, Func<object, bool> canExecuteMethod)
    {
        return new RelayCommand(executeMethod, canExecuteMethod);
    }
}
